#include "QcPickResultListModel.h"
#include "QcPickResultTreeModel.h"

QcPickResultListModel::QcPickResultListModel(QcPickResultTreeModel* treeModel, QObject *parent)
    : QAbstractItemModel(parent)
    , treeModel_(treeModel)
{}

QVariant QcPickResultListModel::headerData(int section, Qt::Orientation orientation, int role) const
{
    return treeModel_->headerData(section, orientation, role);
}

QModelIndex QcPickResultListModel::index(int row, int column, const QModelIndex &parent) const
{
    Q_ASSERT(!parent.isValid());
    return hasIndex(row, column, parent) ? createIndex(row, column) : QModelIndex();
}

QModelIndex QcPickResultListModel::parent(const QModelIndex &index) const
{
    return QModelIndex(); // list模式下，始终返回根节点
}

int QcPickResultListModel::rowCount(const QModelIndex &parent) const
{
    if (parent.isValid())
        return 0;
    return isGroupped() ? gv_.totalSize() : itemAmount(); // 返回总行数
}

int QcPickResultListModel::columnCount(const QModelIndex &parent) const
{
    return treeModel_->columnCount(parent);
}

Qt::ItemFlags QcPickResultListModel::flags(const QModelIndex &index) const
{
    if (!this->checkIndex(index))
        return Qt::ItemFlags{};

    return treeModel_->flags(toTreeIndex_(index));
}

bool QcPickResultListModel::hasChildren(const QModelIndex &parent) const
{
    if (!parent.isValid())
        return isGroupped() ? groupCount() > 0 : itemAmount() > 0;

    return isGroupped() && isGroupRoot(parent.row());
}

QVariant QcPickResultListModel::data(const QModelIndex &index, int role) const
{
    if (!index.isValid())
        return QVariant();

    return treeModel_->data(toTreeIndex_(index), role);
}

bool QcPickResultListModel::setData(const QModelIndex &index, const QVariant &value, int role)
{
    if (treeModel_->setData(toTreeIndex_(index), value, role)) {
        emit dataChanged(index, index, { role });
        return true;
    }

    return false;
}

void QcPickResultListModel::sort(int column, Qt::SortOrder order)
{
    Q_ASSERT(column >= 0 && column < columnCount());
    emit layoutAboutToBeChanged({}, QAbstractItemModel::VerticalSortHint);

    treeModel_->sort(column, order);

    // 同步内部数据
    if (gv_.groups() > 0) {
        gv_.clear();
        for (int i = 0; i < treeModel_->groupCount(); i++)
            gv_.appendGroup(1 + treeModel_->groupSize(i));
    }

    emit layoutChanged({}, QAbstractItemModel::VerticalSortHint);
}

bool QcPickResultListModel::isGroupped() const
{
    return gv_.groups() > 0;
}

bool QcPickResultListModel::isGroupRoot(int row) const
{
    Q_ASSERT(row >= 0 && row < gv_.totalSize() && isGroupped());

    int group = gv_.itemGroup(row);
    return row == gv_.groupStartPos(group); // 分组根节点位于各分组的排头
}

int QcPickResultListModel::groupSize(int groupIdx) const
{
    return treeModel_->groupSize(groupIdx);
}

int QcPickResultListModel::itemAmount() const
{
    return isGroupped() ? (gv_.totalSize() - groupCount())
                        : treeModel_->groupSize(-1);
}

int QcPickResultListModel::listRow(int groupIdx, int itemIdx) const
{
    if (groupIdx >= 0) {
        Q_ASSERT(isGroupped());
        Q_ASSERT(itemIdx >= -1 && itemIdx < groupSize(groupIdx));
        return gv_.itemPos(groupIdx, itemIdx + 1);
    }
    else {
        Q_ASSERT(!isGroupped() && itemIdx >= 0 && itemIdx < itemAmount());
        return itemIdx;
    }
}

QPair<int, int> QcPickResultListModel::groupIndex(int listRow) const
{
    if (!isGroupped())
        return { -1, listRow };

    auto group = gv_.itemGroup(listRow);
    auto row = listRow - gv_.groupStartPos(group);
    return { group, row - 1 };
}

void QcPickResultListModel::appendItem(int group, const QString& filePath)
{
    treeModel_->appendItem(group, filePath);

    if (group >= 0) {

        if (group < groupCount()) { // 向已有分组添加子节点
            gv_.insertItem(group, 0);
        }
        else { // 添加新分组的子节点
            Q_ASSERT(group == groupCount());
            gv_.insertGroup(group);
            gv_.insertItem(group, 0); // 插入根节点
            gv_.insertItem(group, 1); // 插入@filePath
        }
    }
}

void QcPickResultListModel::removeItem(int group, int item)
{
    auto row = listRow(group, item);
    beginRemoveRows(QModelIndex(), row, row);

    treeModel_->removeItem(group, item);

    if (group >= 0) {
        Q_ASSERT(isGroupped());
        gv_.removeItem(group, item + 1);
    }

    endRemoveRows();
    resetInternalData(); // ???
}

void QcPickResultListModel::removeGroup(int group)
{
    if (empty())
        return;

    if (group < 0) {
        beginRemoveRows(QModelIndex(), 0, itemAmount() - 1);
    }
    else {
        auto row = listRow(group, -1);
        beginRemoveRows(QModelIndex(), row, row + groupSize(group));
    }

    treeModel_->removeGroup(group);

    if (group < 0) { // clear
        gv_.clear();
    }
    else {
        gv_.removeGroup(group);
    }

    endRemoveRows();
    resetInternalData(); // ???
}

QModelIndex QcPickResultListModel::toTreeIndex_(const QModelIndex &listIndex) const
{
    if (!listIndex.isValid())
        return QModelIndex();

    auto [group, item] = groupIndex(listIndex.row());
    return treeModel_->treeIndex(group, item, listIndex.column());
}

QModelIndex QcPickResultListModel::fromTreeIndex_(const QModelIndex &treeIndex) const
{
    if (!treeIndex.isValid())
        return QModelIndex();

    auto row = treeIndex.row();
    auto col = treeIndex.column();

    if (isGroupped()) {
        auto root = treeIndex.parent();
        row = root.isValid() ? listRow(root.row(), row) : listRow(row, -1);
    }

    return index(row, col);
}

bool QcPickResultListModel::empty() const
{
    return treeModel_->empty();
}
